home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / CodeWarrior Lite / Metrowerks C⁄C++ Lite / Libraries / Runtime / Common Sources / New.cp < prev    next >
Encoding:
Text File  |  1995-04-27  |  12.9 KB  |  440 lines  |  [TEXT/MMCC]

  1. /************************************************************************/
  2. /*    Project...:    Standard C++ Library                                    */
  3. /*    Name......:    New.cp                                                    */
  4. /*    Purpose...:    standard C++ library                                    */
  5. /*  Copyright.: ©Copyright 1993-95 by metrowerks inc                    */
  6. /************************************************************************/
  7.  
  8. #include <new.h>
  9. #include <Memory.h>
  10.  
  11. #ifdef __MC68K__
  12. #pragma a6frames on
  13. #endif
  14.  
  15. #ifndef NEWMODE
  16. #define NEWMODE NEWMODE_FAST        //    mode used to compile this file
  17. #endif
  18.  
  19. #define NEWMODE_NONE    0            //    do not define operator new/delete
  20. #define NEWMODE_SIMPLE    1            //    call NewPtr/DisposPtr
  21. #define NEWMODE_MALLOC    2            //    use malloc/free
  22. #define NEWMODE_NORMAL    3            //    regular new/delete
  23. #define NEWMODE_FAST    4            //    regular new/delete fast version
  24.  
  25. #ifndef NEWMODE_NORMAL_FASTFREE
  26. #define NEWMODE_NORMAL_FASTFREE    0    //    NEWMODE_NORMAL faster free (real bad fragmentation)
  27. #endif
  28.  
  29.         // These macros allow DebugNew.cp to redefine operators
  30.         // new and delete in debug mode while not adding any overhead
  31.         // for the non-debug case.
  32.  
  33. #ifndef OPERATOR_NEW
  34. #define OPERATOR_NEW operator new
  35. #endif
  36. #ifndef OPERATOR_DELETE
  37. #define OPERATOR_DELETE operator delete
  38. #endif
  39.  
  40. //
  41. //    allow user definitions of operator new/delete
  42. //
  43. extern                void *operator new(size_t size);
  44. #pragma overload    void *operator new(size_t size);
  45.  
  46. extern                void operator delete(void *);
  47. #pragma overload    void operator delete(void *);
  48.  
  49. //extern                void *operator new(size_t size,void *p);    //    this should not be replaceable
  50. //#pragma overload    void *operator new(size_t size,void *p);        //    this should not be replaceable
  51.  
  52. extern void (*new_handler)();
  53.  
  54. #if NEWMODE==NEWMODE_SIMPLE
  55.  
  56. /************************************************************************/
  57. /*    Purpose..:     Allocate memory                                            */
  58. /*    Input....:    size of memory to allocate                                */
  59. /*    Return...:    pointer to memory or 0L                                    */
  60. /************************************************************************/
  61. /*    now inline
  62. void *OPERATOR_NEW(size_t size,void *p)
  63. {
  64.     return p;
  65. }
  66. */
  67.  
  68. /************************************************************************/
  69. /*    Purpose..:     Allocate memory                                            */
  70. /*    Input....:    size of memory to allocate                                */
  71. /*    Return...:    pointer to memory or 0L                                    */
  72. /************************************************************************/
  73. void *OPERATOR_NEW(size_t size)
  74. {
  75.     void *ptr;
  76.  
  77.     while((ptr=NewPtr(size))==NULL)
  78.     {
  79.         if(new_handler) new_handler(); else return(NULL);
  80.     }
  81.     return(ptr);
  82. }
  83.  
  84. /************************************************************************/
  85. /*    Purpose..:     Dispose memory                                            */
  86. /*    Input....:    pointer to memory or 0L (no action if 0L)                */
  87. /*    Return...:    ---                                                        */
  88. /************************************************************************/
  89. void OPERATOR_DELETE(void *ptr)
  90. {
  91.     if(ptr) DisposePtr((Ptr)ptr);
  92. }
  93.  
  94. #elif NEWMODE==NEWMODE_MALLOC
  95.  
  96. #include <stdlib.h>
  97.  
  98. /************************************************************************/
  99. /*    Purpose..:     Allocate memory                                            */
  100. /*    Input....:    size of memory to allocate                                */
  101. /*    Return...:    pointer to memory or 0L                                    */
  102. /************************************************************************/
  103. /*    now inline
  104. void *OPERATOR_NEW(size_t size,void *p)
  105. {
  106.     return p;
  107. }
  108. */
  109.  
  110. /************************************************************************/
  111. /*    Purpose..:     Allocate memory                                            */
  112. /*    Input....:    size of memory to allocate                                */
  113. /*    Return...:    pointer to memory or 0L                                    */
  114. /************************************************************************/
  115. void *OPERATOR_NEW(size_t size)
  116. {
  117.     void *ptr;
  118.  
  119.     while((ptr=malloc(size))==NULL)
  120.     {
  121.         if(new_handler) new_handler(); else return(NULL);
  122.     }
  123.     return(ptr);
  124. }
  125.  
  126. /************************************************************************/
  127. /*    Purpose..:     Dispose memory                                            */
  128. /*    Input....:    pointer to memory or 0L (no action if 0L)                */
  129. /*    Return...:    ---                                                        */
  130. /************************************************************************/
  131. void OPERATOR_DELETE(void *ptr)
  132. {
  133.     free(ptr);
  134. }
  135.  
  136. #elif NEWMODE==NEWMODE_NORMAL
  137.  
  138. typedef struct FreeMemList {
  139.     struct FreeMemList    *next;
  140.     long                size;
  141. }    FreeMemList;
  142.  
  143. static FreeMemList    memlist;                //    dummy header block (always empty)
  144. static size_t _newpoolsize    = 0x00010000L;    //    number of bytes allocated for a new pool
  145. static size_t _newnonptrmax    = 0x00001000L;    //    any object bigger than this will call NewPtr(...) directly 
  146.  
  147. /************************************************************************/
  148. /*    Purpose..:     Set size of future allocation pools                        */
  149. /*    Input....:    size of future allocation pools                            */
  150. /*    Return...:    ---                                                        */
  151. /************************************************************************/
  152. void _set_newpoolsize(size_t size)
  153. {
  154.     _newpoolsize=size;
  155. }
  156.  
  157. /************************************************************************/
  158. /*    Purpose..:     Set NewPtr(...) pointer threshold                        */
  159. /*    Input....:    size of new threshold                                    */
  160. /*    Return...:    ---                                                        */
  161. /************************************************************************/
  162. void _set_newnonptrmax(size_t size)
  163. {
  164.     _newnonptrmax=size;
  165. }
  166.  
  167. /************************************************************************/
  168. /*    Purpose..:     Preallocate an allocation pool                            */
  169. /*    Input....:    size of pool to allocate                                */
  170. /*    Return...:    1: no error; 0:    fail                                    */
  171. /************************************************************************/
  172. char _prealloc_newpool(size_t size)
  173. {
  174.     FreeMemList    *list;
  175.  
  176.     if((list=(FreeMemList *)NewPtr(size))==NULL) return 0;
  177.     list->next=memlist.next; list->size=size; memlist.next=list;
  178.     return 1;
  179. }
  180.  
  181. /************************************************************************/
  182. /*    Purpose..:     Allocate memory                                            */
  183. /*    Input....:    size of memory to allocate                                */
  184. /*    Return...:    pointer to memory or 0L                                    */
  185. /************************************************************************/
  186. /*    now inline
  187. void *OPERATOR_NEW(size_t size,void *p)
  188. {
  189.     return p;
  190. }
  191. */
  192.  
  193. /************************************************************************/
  194. /*    Purpose..:     Allocate memory                                            */
  195. /*    Input....:    size of memory to allocate                                */
  196. /*    Return...:    pointer to memory or 0L                                    */
  197. /************************************************************************/
  198. void *OPERATOR_NEW(size_t size)
  199. {
  200.     Ptr ptr;
  201.  
  202. //    size=(size&0xFFFFFFFC)+8;        //    alloc *4 quantity plus 4 extra bytes for size
  203.     size = 4L + ((size + 3L) & 0xFFFFFFFC);
  204.  
  205.     if(size>=_newnonptrmax)
  206.     {    //    try to get pointer from OS
  207.         while(1)
  208.         {
  209.             if((ptr=NewPtr(size))!=NULL) { *(long *)ptr=-1L; return(ptr+4); }
  210.             if(new_handler) new_handler(); else return(NULL);
  211.         }            
  212.     }
  213.  
  214.     while(1)
  215.     {
  216.         FreeMemList    *list,*prev;
  217.  
  218.         for(prev=&memlist,list=prev->next; list; prev=list,list=list->next) if(size<=list->size)
  219.         {
  220. alloc:        if(list->size>=size+sizeof(FreeMemList))
  221.             {    //    split this free block
  222.                 list->size-=size; ptr=(Ptr)list+list->size;
  223.                 *(long *)ptr=size; return(ptr+4);
  224.             }
  225.             //    remove this block from list
  226.             prev->next=list->next; *(long *)list=list->size; return((Ptr)list+4);
  227.         }
  228.     
  229.         //    not enough free memory in memlist (try to allocate a new Ptr from OS
  230.         if((list=(FreeMemList *)NewPtr(_newpoolsize))==NULL)
  231.         {    //    try to allocate a system block
  232.             if((ptr=NewPtr(size))!=NULL) { *(long *)ptr=-1L; return(ptr+4); }
  233.             if(new_handler) new_handler(); else return(NULL);
  234.         }
  235.         else
  236.         {
  237.             list->next=memlist.next; list->size=_newpoolsize;
  238.             memlist.next=list; prev=&memlist; goto alloc;
  239.         }
  240.     }
  241. }
  242.  
  243. /************************************************************************/
  244. /*    Purpose..:     Dispose memory                                            */
  245. /*    Input....:    pointer to memory or 0L (no action if 0L)                */
  246. /*    Return...:    ---                                                        */
  247. /************************************************************************/
  248. void OPERATOR_DELETE(void *ptr)
  249. {
  250.     if(ptr)
  251.     {
  252.         long    size;
  253.  
  254.         ptr=(Ptr)ptr-4; size=*(long *)ptr;
  255.         if(size!=-1L)
  256.         {
  257.             FreeMemList    *list;
  258. #if !NEWMODE_NORMAL_FASTFREE
  259.             FreeMemList    *prev;
  260.             char        merge=0;
  261.  
  262.             for(prev=&memlist,list=prev->next; list; prev=list,list=list->next)
  263.             {
  264.                 if((Ptr)ptr+size==(Ptr)list)
  265.                 {    //    merge block in front of this list item
  266.                     prev->next=list->next; size+=list->size; list=prev;
  267.                     if(merge) break; else { merge=1; continue; }
  268.                 }
  269.                 if((Ptr)ptr==(Ptr)list+list->size)
  270.                 {    //    merge block at the end of this list item
  271.                     prev->next=list->next; ptr=list; size+=list->size; list=prev;
  272.                     if(merge) break; else { merge=1; continue; }
  273.                 }
  274.             }
  275. #endif
  276.             list=(FreeMemList *)ptr; list->next=memlist.next; list->size=size; memlist.next=list;
  277.         }
  278.         else DisposePtr((Ptr)ptr);
  279.     }
  280. }
  281.  
  282. #elif NEWMODE==NEWMODE_FAST
  283.  
  284. typedef struct MemPool {
  285.     struct MemPool        *next;                //    pointer to next pool
  286.     size_t                size;                //    number of bytes in pool (including header)
  287.     char                data[];                //    variable size user data section
  288. }    MemPool;
  289.  
  290. static MemPool    *mempools;                        //    list of memory pools
  291. static char        *lastfree;                        //    pointer to last free block
  292. static char        *lastend;                        //    pointer to last end
  293. static size_t    _newpoolsize    = 0x00010000L;    //    number of bytes allocated for a new pool
  294. static size_t    _newnonptrmax    = 0x00001000L;    //    any object bigger than this will call NewPtr(...) directly 
  295.  
  296. /************************************************************************/
  297. /*    Purpose..:     Set size of future allocation pools                        */
  298. /*    Input....:    size of future allocation pools                            */
  299. /*    Return...:    ---                                                        */
  300. /************************************************************************/
  301. void _set_newpoolsize(size_t size)
  302. {
  303.     _newpoolsize=size;
  304. }
  305.  
  306. /************************************************************************/
  307. /*    Purpose..:     Set NewPtr(...) pointer threshold                        */
  308. /*    Input....:    size of new threshold                                    */
  309. /*    Return...:    ---                                                        */
  310. /************************************************************************/
  311. void _set_newnonptrmax(size_t size)
  312. {
  313.     _newnonptrmax=size;
  314. }
  315.  
  316. /************************************************************************/
  317. /*    Purpose..:     Preallocate a memory pool                                */
  318. /*    Input....:    size of pool to allocate                                */
  319. /*    Return...:    1: no error; 0:    fail                                    */
  320. /************************************************************************/
  321. char _prealloc_newpool(size_t size)
  322. {
  323.     MemPool    *pool;
  324.  
  325.     if((pool=(MemPool *)NewPtr(size))==NULL) return 0;
  326.  
  327.     pool->next=mempools; mempools=pool;
  328.     pool->size=size; *(long *)pool->data=pool->size-sizeof(MemPool);
  329.  
  330.     return 1;
  331. }
  332.  
  333. /************************************************************************/
  334. /*    Purpose..:     Allocate memory                                            */
  335. /*    Input....:    size of memory to allocate                                */
  336. /*    Return...:    pointer to memory or 0L                                    */
  337. /************************************************************************/
  338. /*    now inline
  339. void *OPERATOR_NEW(size_t size,void *p)
  340. {
  341.     return p;
  342. }
  343. */
  344.  
  345. /************************************************************************/
  346. /*    Purpose..:     Allocate memory                                            */
  347. /*    Input....:    size of memory to allocate                                */
  348. /*    Return...:    pointer to memory or 0L                                    */
  349. /************************************************************************/
  350. void *OPERATOR_NEW(size_t size)
  351. {
  352.     MemPool    *pool;
  353.     char    *ptr,*end;
  354.     long    bsize,nsize;
  355.  
  356. //    size=(size&0xFFFFFFFC)+8; //    alloc *4 quantity plus 4 bytes for size
  357.     size = 4L + ((size + 3L) & 0xFFFFFFFC);
  358.  
  359.     while(1)
  360.     {
  361.         if(size>=_newnonptrmax && (ptr=(char *)NewPtr(size))!=NULL)
  362.         {
  363.             *(long *)ptr=0L; return ptr+4;
  364.         }
  365.  
  366.         if((ptr=lastfree)!=0L && (bsize=*(long *)ptr)>=(long)size)
  367.         {    //    last free block has enough memory left
  368.             end=lastend; goto alloc2;
  369.         }
  370.  
  371.         for(pool=mempools; pool; pool=pool->next)
  372.         {
  373. alloc:        for(ptr=pool->data,end=(Ptr)pool+pool->size; ptr<end;) if((bsize=*(long *)ptr)>0)
  374.             {
  375. alloc2:            lastfree=0L;
  376.                 while(ptr+bsize<end && (nsize=*(long *)(ptr+bsize))>0)
  377.                 {    //    merge block with the next block
  378.                     *(long *)ptr=bsize=bsize+nsize;
  379.                 }
  380.                 if(bsize>=size)
  381.                 {    //    pool block is big enough
  382.                     if(bsize>=size+8)
  383.                     {    //    split this block
  384.                         lastfree=ptr; lastend=end;
  385.                         bsize-=size; *(long *)ptr=bsize; ptr+=bsize;
  386.                         *(long *)ptr=-size; return ptr+4;
  387.                     }
  388.                     else
  389.                     {    //    allocate whole block
  390.                         *(long *)ptr=-bsize; return ptr+4;
  391.                     }
  392.                 }
  393.                 else ptr+=bsize;
  394.             }
  395.             else
  396.             {
  397.                 if(bsize==0) break;        //    corrupt heap?
  398.                 ptr-=bsize;
  399.             }
  400. next:;    }
  401.  
  402.         //    not enough free memory in mempools (try to allocate a new Ptr from OS)
  403.         if((pool=(MemPool *)NewPtr(_newpoolsize))!=NULL)
  404.         {
  405.             pool->next=mempools; mempools=pool;
  406.             pool->size=_newpoolsize; *(long *)pool->data=pool->size-sizeof(MemPool);
  407.             goto alloc;
  408.         }
  409.         else
  410.         {    //    try to allocate a system block
  411.             if((ptr=(char *)NewPtr(size))!=NULL)
  412.             {
  413.                 *(long *)ptr=0L; return ptr+4;
  414.             }
  415.         }
  416.  
  417.         if(new_handler) new_handler(); else return NULL;
  418.     }
  419. }
  420.  
  421. /************************************************************************/
  422. /*    Purpose..:     Dispose memory                                            */
  423. /*    Input....:    pointer to memory or 0L (no action if 0L)                */
  424. /*    Return...:    ---                                                        */
  425. /************************************************************************/
  426. void OPERATOR_DELETE(void *ptr)
  427. {
  428.     if(ptr)
  429.     {
  430.         ptr=(char *)ptr-4;
  431.         if((*(long *)ptr=-*(long *)ptr)==0L) DisposePtr((Ptr)ptr);
  432.     }
  433. }
  434.  
  435. #else
  436.  
  437. //    no operator new/delete defined
  438.  
  439. #endif
  440.